package jokode

import (
	"github.com/pkg/errors"
	"sync"
)

var (
	envLoggerLocker *sync.RWMutex
	envLogProvider  LogProvider

	envLoggerInstance    JoLogger
	envLoggerPlaceHolder JoLogger
)

func init() {
	envLoggerLocker = &sync.RWMutex{}
	envLogProvider = newLoggerProviderZap()
	envLoggerPlaceHolder = &StdLogger{}
	envLoggerInstance = envLoggerPlaceHolder
}

func getLoggerInstance() JoLogger {
	envLoggerLocker.RLock()
	defer envLoggerLocker.RUnlock()
	return envLoggerInstance
}

func getLoggerProvider() LogProvider {
	envLoggerLocker.RLock()
	defer envLoggerLocker.RUnlock()
	return envLogProvider
}

func regLogProviderImpl(provider LogProvider) {
	envLoggerLocker.Lock()
	defer envLoggerLocker.Unlock()

	if provider == nil {
		envLogProvider = nil
		envLoggerInstance = &NoneLogger{}
		return
	} else {
		if tmp := provider.GetLogger(); tmp != nil {
			envLogProvider = provider
			envLoggerInstance = tmp
		} else {
			envLoggerPlaceHolder.Errorf("log provider returns nil logger, use default logger instead.")
			envLogProvider = nil
			envLoggerInstance = envLoggerPlaceHolder
		}
	}
}

func initLoggerConfigImpl(logCfg *LogConfig) error {
	provider := getLoggerProvider()
	if provider == nil {
		panic("logger provider is nil.")
	}

	envLoggerLocker.Lock()
	defer envLoggerLocker.Unlock()

	if logger, err := provider.InitLogger(logCfg); err != nil {
		return errors.Wrapf(err, "try init logger by provider '%s' fail", provider.GetName())
	} else if logger == nil {
		return errors.Errorf("logger provider '%s' returns nil logger", provider.GetName())
	} else {
		envLoggerInstance = logger
	}

	return nil
}
